package com.yunhe.option.service.base.impl;

import com.alibaba.fastjson.JSON;
import com.yunhe.common.exception.ArgumentErrorException;
import com.yunhe.common.exception.ObjectNotFoundException;
import com.yunhe.common.exception.UniqueConstraintsException;
import com.yunhe.common.util.CollectionUtil;
import com.yunhe.common.util.RedisClient;
import com.yunhe.common.util.StringUtil;
import com.yunhe.option.domain.base.Enum;
import com.yunhe.option.domain.base.Item;
import com.yunhe.option.repository.base.EnumRepository;
import com.yunhe.option.repository.base.ItemRepository;
import com.yunhe.option.service.base.ItemService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @ClassName ItemServiceImpl
 * @Description TODO
 * @Author HeTao
 * @Date 2021/2/26 14:55
 * @Version 1.0
 **/
@Service
public class ItemServiceImpl implements ItemService {

    @Autowired
    private ItemRepository itemRepository;

    @Autowired
    private EnumRepository enumRepository;

    @Autowired
    private RedisClient redisClient;

    @Override
    public Iterable<Item> findByEnumId(Long enumId) {
        return itemRepository.findByEnumId(enumId);
    }

    @Override
    public Item createItem(Long enumId, Long parentId, Item item) throws UniqueConstraintsException, ArgumentErrorException, ObjectNotFoundException {
        item.setId(null);
        if(StringUtil.isEmpty(item.getSn())){
            item.setSn(String.valueOf(System.currentTimeMillis()));
        }
        Enum enums = enumRepository.findById(enumId).orElse(null);
        if(enums == null){
            throw new ArgumentErrorException("对应枚举不存在，请重新选择!");
        }
        processBeforeSave(item,parentId,enumId);
        Item newItem = itemRepository.save(item);

        //条目与枚举进行绑定
        if(parentId == null){
            itemRepository.bindEnum(enumId,newItem.getId());
        }
        //进行关系绑定
        if(parentId != null){
            bindParent(newItem,parentId);
        }

        //查询，存放redis
        List<Item>  items = (List<Item>) this.getItemByItemCodeAndEnumName(enums.getName());
        if(!CollectionUtil.isEmpty(items)){
            redisClient.set("ENUM_ITEM:"+enums.getName(), JSON.toJSONString(items));
        }
        return newItem;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public Item updateItem(Item item) throws ObjectNotFoundException, UniqueConstraintsException, ArgumentErrorException {
        Item itemId = findByItemId(item.getId());
        if(itemId == null) {
            throw new ObjectNotFoundException("找不到ID为" + item.getId() + "的条目");
        }
        List<Item> items = (List<Item>) itemRepository.findChildItemByParentId(itemId.getId());
        item.setChildren(items);
        Item newItem = itemRepository.save(item);
        Enum enums =enumRepository.findEnumByItemId(newItem.getId());
        //查询，存放redis
        List<Item>  itemList = (List<Item>) this.getItemByItemCodeAndEnumName(enums.getName());
        if(!CollectionUtil.isEmpty(itemList)){
            redisClient.set("ENUM_ITEM:"+enums.getName(), JSON.toJSONString(itemList));
        }
        return newItem;
    }

    @Override
    @Transactional(rollbackFor = Exception.class, transactionManager = "transactionManager")
    public void delete(Long id) throws ArgumentErrorException {
        Enum enums =enumRepository.findEnumByItemId(id);
        //查询，存放redis
        //查询该条目是否有子条目
        Iterable<Item> items = itemRepository.findChildItemByParentId(id);
        if(items != null && items.iterator().hasNext()){
            throw new ArgumentErrorException("该条目下存在子条目不能删除！");
        }
        itemRepository.unbindParentItemById(id);
        itemRepository.unbindEnumById(id);
        itemRepository.deleteById(id);
        //查询，存放redis
        List<Item>  itemList = (List<Item>) this.getItemByItemCodeAndEnumName(enums.getName());
        if(!CollectionUtil.isEmpty(itemList)){
            redisClient.set("ENUM_ITEM:"+enums.getName(), JSON.toJSONString(itemList));
        }
    }

    @Override
    public Item getItemById(Long id) throws ObjectNotFoundException {
        Item item = findByItemId(id);
        if(item == null){
            throw new ObjectNotFoundException("找不到ID为" + id + "的条目");
        }
        return item;
    }

    @Override
    public Iterable<Item> getItemByEnumName(String enumName) {
        return itemRepository.getItemByEnumName(enumName);
    }

    @Override
    public Iterable<Item> getChildItemsById(Long id) {
        return itemRepository.findChildItemByParentId(id);
    }

    @Override
    public Iterable<Item> getAllItems(String enumName) {
        List<Item> results = (List<Item>)itemRepository.findItemsByEnumName(enumName);
        //这种查询有一个问题，会将孩子节点也一并放入List中
        //需要将孩子节点从List中移除
        removeRepeatChild(results);
        sortItems(results);
        return results;
    }

    @Override
    public Iterable<Item> getItemByItemCodeAndEnumName(String name) {
        Iterable<Item> items = itemRepository.findItemsByEnumName(name);
        if(items != null && items.iterator().hasNext()){
            for (Item item : items) {
                item.setChildren(null);
            }
        }
        return items;
    }




    private void sortItems(List<Item> itemList) {
        if (itemList != null && itemList.size() > 0) {
            Collections.sort(itemList);
            for (Item item : itemList) {
                if (item.getChildren() != null && item.getChildren().size() > 0) {
                    sortItems(item.getChildren());
                }
            }
        }
    }

    private void removeRepeatChild(List<Item> results) {
        if (results != null && results.size() > 0) {
            //保存重复的ID
            Map<Long, Object> repeatIdMap = new HashMap<>();
            //第一次循环，获得所有孩子节点ID
            for (Item item : results) {
                List<Item> children =  item.getChildren();
                if (children != null && children.size() > 0) {
                    for (Item child: children) {
                        repeatIdMap.put(child.getId(), null);
                    }
                }
            }
            //根据是否是孩子节点移除元素
            for (int i = results.size() - 1; i >= 0; i--) {
                Item item = results.get(i);
                if (repeatIdMap.containsKey(item.getId())) {
                    results.remove(i);
                }
            }
        }
    }

    private void bindParent(Item newItem, Long parentId) throws ObjectNotFoundException {
        if (newItem != null) {
            itemRepository.unbindParentItemById(newItem.getId());
        }
        if (parentId != null && parentId != -1) {
            Item parentItem = findByItemId(parentId);
            if (parentItem == null) {
                throw new ObjectNotFoundException("找不到ID为" + parentId + "的父条目");
            }
            itemRepository.bindChildItemById(parentId, newItem.getId());
        }
    }

    private Item findByItemId(Long id) {
        return itemRepository.findById(id).orElse(null);
    }

    private void processBeforeSave(Item item, Long parentId, Long enumId) throws ArgumentErrorException, UniqueConstraintsException {
        if(StringUtil.isEmpty(item.getCode()) || StringUtil.isEmpty(item.getTitle())){
            throw new ArgumentErrorException("条目编码、条目标题不能为空！");
        }
        if(enumId == null){
            throw new ArgumentErrorException("请选择对应的枚举进行操作！");
        }
        //校验对应枚举下的code是否存在
        if(parentId == null){
            Item itemByCode = itemRepository.findByEnumIdAndCode(enumId,item.getCode());
            if(itemByCode != null){
                if(item.getId() ==null || item.getId().longValue() != itemByCode.getId().longValue()){
                    throw new UniqueConstraintsException("对应枚举下已经存在条目code为"+item.getCode()+"的条目");
                }
            }
        }else {
            Item itemByCode = itemRepository.findByEnumIdAndCode(enumId,item.getCode(),parentId);
            if(itemByCode != null){
                if(item.getId() ==null || item.getId().longValue() != itemByCode.getId().longValue()){
                    throw new UniqueConstraintsException("对应枚举下已经存在条目code为"+item.getCode()+"的条目");
                }
            }
        }
    }
}
